package com.edu.tool.config.mybatis;


import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.IdType;

import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.MybatisXMLLanguageDriver;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.edu.tool.config.TenantDBHandler;
import com.edu.tool.config.mybatis.datasource.DynamicDataSource;
import org.apache.ibatis.mapping.DatabaseIdProvider;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.baomidou.mybatisplus.annotation.DbType.MYSQL;

@Configuration
@EnableTransactionManagement
public class MybatisConf {
//
//    /*
//     * 解决引入TK Mapper后，加载顺序错误的问题
//     * */
//    @Bean
//    public static MapperScannerConfigurer mapperScannerConfigurer() {
//        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
//        mapperScannerConfigurer.setBasePackage("com.edumaven.crm.mapper");//扫描该路径下的dao
//        Properties properties = new Properties();
//        properties.setProperty("mappers", "com.edumaven.crm.util.BaseMapper");//通用dao
//        properties.setProperty("notEmpty", "false");
//        properties.setProperty("IDENTITY", "MYSQL");
//        mapperScannerConfigurer.setProperties(properties);
//        return mapperScannerConfigurer;
//    }

////    /*
////    * 引入Tk Mybatis的PageHelper，做分页功能
////    * */
//    @Bean
//    public PageHelper pageHelper() {
//        System.out.println("MyBatisConfiguration.pageHelper()");
//        PageHelper pageHelper = new PageHelper();
//        Properties p = new Properties();
//        p.setProperty("dialect", "com.github.pagehelper.dialect.helper.MySqlDialect");
//        p.setProperty("offsetAsPageNum", "true");
//        p.setProperty("rowBoundsWithCount", "true");
//        p.setProperty("reasonable", "true");
//        pageHelper.setProperties(p);
//        return pageHelper;
//    }


    @Bean(name = "masterDS")
    @ConfigurationProperties(prefix = "spring.datasource2.centerdb")
    public DataSource   masterDS(/*@Qualifier("exs")ExceptionSorter exceptSorter*/) throws SQLException {
        DruidDataSource ds = new DruidDataSource();
        ds.setExceptionSorter( "com.alibaba.druid.pool.vendor.MySqlExceptionSorter");
        return ds;
    }


     /**
      * 动态数据源: 通过AOP在不同数据源之间动态切换
      * @return
      */
    @Primary
    @Bean(name = "dynamicDS")
    public   DataSource dynamicDS(@Qualifier("masterDS") DataSource dataSource )  throws SQLException {


       DynamicDataSource dynamicDataSource = new DynamicDataSource();

       // 默认数据源
       dynamicDataSource.setDefaultTargetDataSource(dataSource );

        // 配置多数据源
        Map<Object, Object> dsMap = new HashMap(5);
        dsMap.put("masterDS", dataSource);
        dynamicDataSource.setTargetDataSources(dsMap);

        return dynamicDataSource;
    }

    /**
     *缺省配置事务管理器
     */

    @Bean
    public   PlatformTransactionManager transactionManager( @Qualifier("dynamicDS") DataSource dataSource ) throws SQLException
    {
        DataSource ds = dataSource;
        return new  DataSourceTransactionManager(dataSource );
    }


    /**
     * mybatis-plus分页插件<br>
     * 文档：http://mp.baomidou.com<br>
     */
    @Bean
    public   PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();

        /*
         * 【测试多租户】 SQL 解析处理拦截器<br>
         * 这里固定写成住户 1 实际情况你可以从cookie读取，因此数据看不到 【 麻花藤 】 这条记录（ 注意观察 SQL ）<br>
         */
        List<ISqlParser> sqlParserList = new ArrayList<ISqlParser>();
        TenantSqlParser tenantSqlParser = new TenantSqlParser();
        tenantSqlParser.setTenantHandler(new TenantDBHandler()
        );

        sqlParserList.add(tenantSqlParser);
        paginationInterceptor.setSqlParserList(sqlParserList);

        return paginationInterceptor;
    }

    /**

     */
    @Bean
    public   GlobalConfig globalConfig() {
        GlobalConfig globalConfig = new GlobalConfig();

        GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();

        dbConfig.setDbType(MYSQL);
        dbConfig.setIdType(IdType.AUTO);
        dbConfig.setFieldStrategy(FieldStrategy.NOT_EMPTY);
        globalConfig.setDbConfig(dbConfig);
        globalConfig.setRefresh(true);
        globalConfig.setSqlParserCache(true);

        return globalConfig;
    }





    @Bean
    public  SqlSessionFactory sqlSessionFactory( @Qualifier("dynamicDS") DataSource dataSource ,
                                                      ObjectProvider<Interceptor[]> interceptorsProvider,
                                                      ObjectProvider<GlobalConfig> globalConfigProvider,
                                                      ObjectProvider<DatabaseIdProvider> databaseIdProvider )
            throws Exception  {

        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource );
        sqlSessionFactoryBean.setVfs(SpringBootVFS.class);

        //这个语句与下面MybatisConfiguration的一组语句可以二选一。
        //sqlSessionFactoryBean.setConfigLocation( resourceLoader.getResource("classpath:mybatis-config.xml"));

        MybatisConfiguration mc = new MybatisConfiguration();
        mc.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
        mc.setMapUnderscoreToCamelCase(false);
        mc.setCacheEnabled(false);
        mc.setLogImpl(org.apache.ibatis.logging.stdout.StdOutImpl.class);
        mc.setDefaultExecutorType(ExecutorType.REUSE);
        sqlSessionFactoryBean.setConfiguration(mc);



        //以下部分是mybatis plus 新增的功能,这些功能在mybatis中配置会比较麻烦。
        // 这些功能在mybatis plus 中需要指定package就可以了。
        Interceptor[]  interceptors = (Interceptor[])interceptorsProvider.getIfAvailable();
        if(interceptors != null) {
            sqlSessionFactoryBean.setPlugins(interceptors);
        }
        DatabaseIdProvider dbprovider =  databaseIdProvider.getIfAvailable();
        if(dbprovider != null)
           sqlSessionFactoryBean.setDatabaseIdProvider(dbprovider);

        GlobalConfig globalConfig = globalConfigProvider.getIfAvailable();
        if(globalConfig != null)
            sqlSessionFactoryBean.setGlobalConfig(globalConfig);

        sqlSessionFactoryBean.setTypeAliasesPackage( "com.edu.tool.bean");
        sqlSessionFactoryBean.setTypeEnumsPackage("com.edu.tool.constant.enums");

        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        Resource  mapperlocs[]  = resolver.getResources("classpath:/mapper/*Mapper.xml");

        sqlSessionFactoryBean.setMapperLocations(mapperlocs);

        return sqlSessionFactoryBean.getObject();
    }



    /**
     * 相当于顶部的：
     * {@code @MapperScan("com.baomidou.springboot.mapper*")}
     * 这里可以扩展，比如使用配置文件来配置扫描Mapper的路径
     */
    @Bean
    public static MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer scannerConfigurer = new MapperScannerConfigurer();

        //scannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        scannerConfigurer.setBasePackage("com.edu.tool.mapper*");

        return scannerConfigurer;
    }



//    //配置Druid相关的bean
//    @Bean
//    public static ServletRegistrationBean druidServlet() {
//
//        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
//        //登录查看信息的账号密码.
//
//        servletRegistrationBean.addInitParameter("username","Admin");
//        servletRegistrationBean.addInitParameter("password","123456");
//        return servletRegistrationBean;
//    }
//
//    @Bean
//    public static FilterRegistrationBean filterRegistrationBean() {
//        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
//        filterRegistrationBean.setFilter(new WebStatFilter());
//        filterRegistrationBean.addUrlPatterns("/*");
//        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
//        return filterRegistrationBean;
//    }
}
